<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
	
	<link rel="stylesheet" href="styles.css">

	<script type="importmap">
	  {
		"imports": {
		  "three": "https://cdn.jsdelivr.net/npm/three@0.164.0/build/three.module.js",
		  "three/addons/": "https://cdn.jsdelivr.net/npm/three@0.164.0/examples/jsm/",
		  "pet/": "https://cdn.jsdelivr.net/npm/pet-gen@1.7.1/src/"
		}
	  }
	</script>
</head>

<body>
	<div class="header white">
		<h1 class="white">Project goals</h1>
		<h3 class="white">Normal texture —vs— Equirectangular texture —vs— Equirectangular texture + shader fix</h3>
	</div>
	
	<div class="footnote white">
		<a href="#" onclick="window.history.back(); return false;">Back</a>
	</div>	
	
	<script type="module">

		import * as THREE from "three";
		import { OrbitControls } from "three/addons/controls/OrbitControls.js";
		import * as PET from "pet/texture-generator.js";




		// setting up the scene

		var scene = new THREE.Scene();
		scene.background = new THREE.Color( 'black' );

		var camera = new THREE.PerspectiveCamera( 5, innerWidth/innerHeight );
		camera.position.set( 0, 0, 100 );
		camera.lookAt( scene.position );

		var renderer = new THREE.WebGLRenderer( { antialias: true } );
		renderer.setSize( innerWidth, innerHeight );
		renderer.setAnimationLoop( animationLoop );
		document.body.appendChild( renderer.domElement );

		window.addEventListener( "resize", ( /*event*/ ) => {

			camera.aspect = innerWidth/innerHeight;
			camera.updateProjectionMatrix( );
			renderer.setSize( innerWidth, innerHeight );

		} );

		var hiddenCamera = camera.clone();
		hiddenCamera.position.set( 0, 0, 1 );

		var controls = new OrbitControls( hiddenCamera, renderer.domElement );
		controls.enableDamping = true;
		controls.autoRotate = !true;
		controls.autoRotateSpeed = 0.5;

		var light = new THREE.PointLight( 'white', 4 );
		light.position.set( 0, 0, 100 );
		light.decay = 0;
		scene.add( light );


		const W = 512;
		const H = 256;
		const S = 32;



		// left scene

		var canvas = document.createElement( 'canvas' );
		canvas.width = W;
		canvas.height = H;

		var context = canvas.getContext( '2d' );
		context.fillStyle = 'white';
		context.fillRect( 0, 0, W, H );
		context.fillStyle = 'black';

		context.filter = "blur(6px)";
		for ( var y=-1; y<H/S/2+1; y++ )
			for ( var x=-1; x<W/S+1; x++ )
				if ( ( x+y )%2 ) 		{

					context.beginPath( );
					context.arc( S*x, S*y, 20, 0, 2*Math.PI );
					context.fill( );

				}

		context.filter = "none";
		for ( var y=-1; y<H/S/2+1; y++ )
			for ( var x=-1; x<W/S+1; x++ )
				if ( ( x+y )%2 ) 		{

					context.beginPath( );
					context.arc( S*x, S*y, S/2, 0, 2*Math.PI );
					context.fill( );

				}

		context.fillStyle = 'white';
		context.fillRect( 0, H/2, W, H/2 );

		context.fillStyle = 'black';
		for ( var x=0; x<=W; x+=S/2 )
			context.fillRect( x-2, H/2, 5, W/2 );

		context.fillRect( 0, H/2-8, W, 16 );

		var leftBallUp = new THREE.Mesh(
			new THREE.SphereGeometry( 1, 16, 8 ),
			new THREE.MeshLambertMaterial( {
				map: new THREE.CanvasTexture( canvas )
			} )
		);

		var leftBallDown = new THREE.Mesh(
			new THREE.SphereGeometry( 1, 60, 30 ),
			new THREE.MeshLambertMaterial( {
				map: new THREE.CanvasTexture( canvas )
			} )
		);

		var leftPanel = new THREE.Mesh(
			new THREE.PlaneGeometry( 2.8, 1.4 ),
			leftBallUp.material
		);

		leftBallUp.position.set( -3, 2, 0 );
		leftBallDown.position.set( -3, -2, 0 );
		leftPanel.position.set( -3, 0, 0 );

		scene.add( leftBallUp, leftBallDown, leftPanel );



		// middle scene

		var vec = new THREE.Vector3();

		var dotPositions = new THREE.IcosahedronGeometry( 1, 1 ).getAttribute( 'position' );
		var dotPoints = [];
		for ( var i=0; i<dotPositions.count; i++ )
			dotPoints.push( new THREE.Vector3().fromBufferAttribute( dotPositions, i ) );

		function pattern( x, y, z, color, options, u, v, px, py ) 		{

			vec.set( z, y, x );

			var dist = 1e10;
			for ( var point of dotPoints )
				dist = Math.min( dist, vec.distanceTo( point ) );

			var k = Math.max( 0, 1-0.005/dist**3.1 );


			if ( py>H/2-8 && py<H/2+8 )
				color.set( 0, 0, 0 );
			else
				if ( v<0.5 ) {

					k = k**0.5;
					color.set( k, k, k );

				} else {

					k = 1.3-( Math.sin( 16*Math.PI*z ) );
					color.set( k, k, k );

				}

		}

		var midBallUp = new THREE.Mesh(
			new THREE.SphereGeometry( 1, 16, 8 ),
			new THREE.MeshLambertMaterial( { map: PET.texture( pattern, { width: W, height: H } ) } )
		);

		var midBallDown = new THREE.Mesh(
			new THREE.SphereGeometry( 1, 60, 30 ),
			midBallUp.material
		);

		var midPanel = new THREE.Mesh(
			new THREE.PlaneGeometry( 2.8, 1.4 ),
			midBallUp.material
		);

		midBallUp.position.set( 0, 2, 0 );
		midBallDown.position.set( 0, -2, 0 );

		scene.add( midBallUp, midBallDown, midPanel );




		// right scene

		var rightBallUp = new THREE.Mesh(
			new THREE.SphereGeometry( 1, 16, 8 ),
			PET.material( new THREE.MeshLambertMaterial( { map: midBallUp.material.map } ) )
		);

		var rightBallDown = new THREE.Mesh(
			new THREE.SphereGeometry( 1, 60, 30 ),
			rightBallUp.material
		);

		var rightPanel = new THREE.Mesh(
			new THREE.PlaneGeometry( 2.8, 1.4 ),
			new THREE.MeshLambertMaterial( { map: rightBallUp.material.map } )
		);

		rightBallUp.position.set( 3, 2, 0 );
		rightBallDown.position.set( 3, -2, 0 );
		rightPanel.position.set( 3, 0, 0 );

		scene.add( rightBallUp, rightBallDown, rightPanel );


		function animationLoop( /*t*/ ) {

			controls.update( );

			for ( var ball of [ leftBallUp, leftBallDown, midBallUp, midBallDown, rightBallUp, rightBallDown ]) {

				ball.scale.setScalar( 1/controls.getDistance() );
				ball.quaternion.copy( hiddenCamera.quaternion ).conjugate();

			}

			renderer.render( scene, camera );

		}

	</script>
</body>
</html>